{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "import torch.optim as optim\n",
    "from torchvision import datasets, transforms\n",
    "import argparse\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'cat': 0, 'dog': 1}\n",
      "['cat', 'dog']\n"
     ]
    }
   ],
   "source": [
    "#数据加载\n",
    "from torchvision.datasets import ImageFolder\n",
    "simple_transform = transforms.Compose([transforms.Resize((256,256))\n",
    "                                       ,transforms.ToTensor()\n",
    "                                       ,transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n",
    "                                      ])\n",
    "train_data = ImageFolder('../chapter4/DogVsCatData/train',simple_transform)\n",
    "print(train_data.class_to_idx)\n",
    "print(train_data.classes) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "#定义模型\n",
    "class DogCat_Net(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(DogCat_Net,self).__init__()\n",
    "        #RGB对应Channel=3，定义16个卷积核，卷积核大小为7，膨胀率为2\n",
    "        self.conv1 = nn.Conv2d(3, 4, kernel_size=7,dilation=2)\n",
    "        self.conv2 = nn.Conv2d(4, 16, kernel_size=5)\n",
    "        self.conv2_drop = nn.Dropout2d()\n",
    "        self.fc1 = nn.Linear(55696, 1000)\n",
    "        self.fc2 = nn.Linear(1000,50)\n",
    "        self.fc3 = nn.Linear(50, 2)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = F.relu(F.max_pool2d(self.conv1(x), 2))\n",
    "        x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))\n",
    "        x = x.view(-1, 55696)\n",
    "        x = F.relu(self.fc1(x))\n",
    "        x = F.dropout(x)\n",
    "        x = F.relu(self.fc2(x))\n",
    "        x = F.dropout(x)\n",
    "        x = self.fc3(x)\n",
    "        return F.log_softmax(x,dim=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train(args, model, device, dataloader_kwargs):\n",
    "    global_step = 0\n",
    "    #手动设置随机种子\n",
    "    torch.manual_seed(args.get(\"seed\"))\n",
    "    #加载训练数据\n",
    "    train_loader = torch.utils.data.DataLoader(args.get(\"train_data\"),batch_size=args.get(\"batch_size\"),num_workers=6,shuffle=True,**dataloader_kwargs)\n",
    "    \n",
    "    #使用随机梯度下降进行优化\n",
    "    optimizer = optim.SGD(model.parameters(), lr=args.get(\"lr\"), momentum=args.get(\"momentum\"))\n",
    "    #开始训练，训练epoches次\n",
    "    for epoch in range(1, args.get(\"epochs\") + 1):\n",
    "        global_step = train_epoch(epoch, args, model, device, train_loader, optimizer,global_step)\n",
    "\n",
    "\n",
    "\n",
    "def train_epoch(epoch, args, model, device, data_loader, optimizer,global_step):\n",
    "    #模型转换为训练模式\n",
    "    model.train()\n",
    "    pid = os.getpid()\n",
    "    for batch_idx, (data, target) in enumerate(data_loader):\n",
    "        #优化器梯度置0\n",
    "        optimizer.zero_grad()\n",
    "        #输入特征预测值\n",
    "        output = model(data.to(device))\n",
    "        #预测值与标准值计算损失\n",
    "        loss = F.nll_loss(output, target.to(device))\n",
    "        #计算梯度\n",
    "        loss.backward()\n",
    "        #更新梯度\n",
    "        optimizer.step()\n",
    "        #每log_interval步打印一下日志\n",
    "        if batch_idx % args.get(\"log_interval\") == 0:\n",
    "            global_step += 1\n",
    "            viz.line(Y=np.array([loss.item()]), X=np.array([global_step]), update='append', win=args.get(\"loss_win\"))\n",
    "            print('{}\\tTrain Epoch: {} [{}/{} ({:.2f}%)]\\tLoss: {:.12f}'.format(pid, epoch, batch_idx * len(data), len(data_loader.dataset),\n",
    "                                                                               100. * batch_idx / len(data_loader), loss.item()))\n",
    "    return global_step"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import visdom\n",
    "import numpy as np\n",
    "viz = visdom.Visdom(port=8097, server=\"127.0.0.1\",env=\"Test\")\n",
    "# line updates\n",
    "loss_win = viz.line(np.arange(1))\n",
    "#超参数及默认值\n",
    "args={\n",
    "    'batch_size':128,\n",
    "    'epochs':50,\n",
    "    'lr':0.01,\n",
    "    'momentum':0.9,\n",
    "    'seed':1,\n",
    "    'log_interval':30,\n",
    "    'train_data':train_data,\n",
    "    'loss_win':loss_win\n",
    "}\n",
    "use_cuda=True if torch.cuda.is_available() else False\n",
    "\n",
    "if __name__==\"__main__\":\n",
    "    #运行时设备\n",
    "    device = torch.device(\"cuda\" if use_cuda else \"cpu\")\n",
    "    torch.cuda.empty_cache()\n",
    "    #使用固定缓冲区\n",
    "    dataloader_kwargs = {'pin_memory': True} if use_cuda else {}\n",
    "    #模型拷贝到设备\n",
    "    model = DogCat_Net().to(device)\n",
    "    train(args, model,device, dataloader_kwargs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 用Vgg16模型训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def vgg_train(args, vgg, device, dataloader_kwargs):\n",
    "    global_step = 0\n",
    "    #手动设置随机种子\n",
    "    torch.manual_seed(args.get(\"seed\")+1)\n",
    "    #加载训练数据\n",
    "    train_loader = torch.utils.data.DataLoader(args.get(\"train_data\"),batch_size=args.get(\"batch_size\"),num_workers=6,shuffle=True,**dataloader_kwargs)\n",
    "    \n",
    "    #使用随机梯度下降进行优化\n",
    "    optimizer = optim.SGD(vgg.parameters(), lr=args.get(\"lr\"), momentum=args.get(\"momentum\"))\n",
    "    #开始训练，训练epoches次\n",
    "    for epoch in range(1, args.get(\"epochs\") + 1):\n",
    "        global_step = vgg_train_epoch(epoch, args, vgg, device, train_loader, optimizer,global_step)\n",
    "\n",
    "\n",
    "\n",
    "def vgg_train_epoch(epoch, args, vgg, device, data_loader, optimizer,global_step):\n",
    "    #模型转换为训练模式\n",
    "    vgg.train()\n",
    "    pid = os.getpid()\n",
    "    for batch_idx, (data, target) in enumerate(data_loader):\n",
    "        #优化器梯度置0\n",
    "        optimizer.zero_grad()\n",
    "        #输入特征预测值\n",
    "        output = F.log_softmax(vgg(data.to(device)))\n",
    "        #预测值与标准值计算损失\n",
    "        loss = F.nll_loss(output.narrow(1,0,2),target.to(device))\n",
    "        #计算梯度\n",
    "        loss.backward()\n",
    "        #更新梯度\n",
    "        optimizer.step()\n",
    "        #每10步打印一下日志\n",
    "        if batch_idx % 10 == 0:\n",
    "            global_step += 1\n",
    "            viz.line(Y=np.array([loss.item()]), X=np.array([global_step]), update='append', win=args.get(\"loss_win\"))\n",
    "            print('{}\\tTrain Epoch: {} [{}/{} ({:.2f}%)]\\tLoss: {:.12f}'.format(pid, epoch, batch_idx * len(data), len(data_loader.dataset),\n",
    "                                                                               100. * batch_idx / len(data_loader), loss.item()))\n",
    "    return global_step"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:root:Setting up a new session...\n",
      "D:\\softwares\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:24: UserWarning: Implicit dimension choice for log_softmax has been deprecated. Change the call to include dim=X as an argument.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "20632\tTrain Epoch: 1 [0/22587 (0.00%)]\tLoss: 0.671515882015\n",
      "20632\tTrain Epoch: 1 [320/22587 (1.42%)]\tLoss: 0.599117100239\n",
      "20632\tTrain Epoch: 1 [640/22587 (2.83%)]\tLoss: 0.579360485077\n",
      "20632\tTrain Epoch: 1 [960/22587 (4.25%)]\tLoss: 0.489593654871\n",
      "20632\tTrain Epoch: 1 [1280/22587 (5.67%)]\tLoss: 0.371161013842\n",
      "20632\tTrain Epoch: 1 [1600/22587 (7.08%)]\tLoss: 0.342235237360\n",
      "20632\tTrain Epoch: 1 [1920/22587 (8.50%)]\tLoss: 0.318746000528\n",
      "20632\tTrain Epoch: 1 [2240/22587 (9.92%)]\tLoss: 0.283182859421\n",
      "20632\tTrain Epoch: 1 [2560/22587 (11.33%)]\tLoss: 0.286416947842\n",
      "20632\tTrain Epoch: 1 [2880/22587 (12.75%)]\tLoss: 0.275277584791\n",
      "20632\tTrain Epoch: 1 [3200/22587 (14.16%)]\tLoss: 0.283171862364\n",
      "20632\tTrain Epoch: 1 [3520/22587 (15.58%)]\tLoss: 0.288028866053\n",
      "20632\tTrain Epoch: 1 [3840/22587 (17.00%)]\tLoss: 0.295131027699\n",
      "20632\tTrain Epoch: 1 [4160/22587 (18.41%)]\tLoss: 0.174489945173\n",
      "20632\tTrain Epoch: 1 [4480/22587 (19.83%)]\tLoss: 0.187735587358\n",
      "20632\tTrain Epoch: 1 [4800/22587 (21.25%)]\tLoss: 0.195627152920\n",
      "20632\tTrain Epoch: 1 [5120/22587 (22.66%)]\tLoss: 0.218818157911\n",
      "20632\tTrain Epoch: 1 [5440/22587 (24.08%)]\tLoss: 0.205103665590\n",
      "20632\tTrain Epoch: 1 [5760/22587 (25.50%)]\tLoss: 0.188047438860\n",
      "20632\tTrain Epoch: 1 [6080/22587 (26.91%)]\tLoss: 0.181155815721\n",
      "20632\tTrain Epoch: 1 [6400/22587 (28.33%)]\tLoss: 0.186658158898\n",
      "20632\tTrain Epoch: 1 [6720/22587 (29.75%)]\tLoss: 0.172390639782\n",
      "20632\tTrain Epoch: 1 [7040/22587 (31.16%)]\tLoss: 0.151106387377\n",
      "20632\tTrain Epoch: 1 [7360/22587 (32.58%)]\tLoss: 0.213158831000\n",
      "20632\tTrain Epoch: 1 [7680/22587 (33.99%)]\tLoss: 0.111520797014\n",
      "20632\tTrain Epoch: 1 [8000/22587 (35.41%)]\tLoss: 0.136186361313\n",
      "20632\tTrain Epoch: 1 [8320/22587 (36.83%)]\tLoss: 0.158286660910\n",
      "20632\tTrain Epoch: 1 [8640/22587 (38.24%)]\tLoss: 0.135694742203\n",
      "20632\tTrain Epoch: 1 [8960/22587 (39.66%)]\tLoss: 0.165918305516\n",
      "20632\tTrain Epoch: 1 [9280/22587 (41.08%)]\tLoss: 0.126596122980\n",
      "20632\tTrain Epoch: 1 [9600/22587 (42.49%)]\tLoss: 0.276793986559\n",
      "20632\tTrain Epoch: 1 [9920/22587 (43.91%)]\tLoss: 0.148243561387\n",
      "20632\tTrain Epoch: 1 [10240/22587 (45.33%)]\tLoss: 0.127290457487\n",
      "20632\tTrain Epoch: 1 [10560/22587 (46.74%)]\tLoss: 0.094548806548\n",
      "20632\tTrain Epoch: 1 [10880/22587 (48.16%)]\tLoss: 0.101339340210\n",
      "20632\tTrain Epoch: 1 [11200/22587 (49.58%)]\tLoss: 0.169287472963\n",
      "20632\tTrain Epoch: 1 [11520/22587 (50.99%)]\tLoss: 0.097163520753\n",
      "20632\tTrain Epoch: 1 [11840/22587 (52.41%)]\tLoss: 0.071454316378\n",
      "20632\tTrain Epoch: 1 [12160/22587 (53.82%)]\tLoss: 0.116720125079\n",
      "20632\tTrain Epoch: 1 [12480/22587 (55.24%)]\tLoss: 0.186790511012\n",
      "20632\tTrain Epoch: 1 [12800/22587 (56.66%)]\tLoss: 0.098669588566\n",
      "20632\tTrain Epoch: 1 [13120/22587 (58.07%)]\tLoss: 0.101514145732\n",
      "20632\tTrain Epoch: 1 [13440/22587 (59.49%)]\tLoss: 0.121860355139\n",
      "20632\tTrain Epoch: 1 [13760/22587 (60.91%)]\tLoss: 0.069861471653\n",
      "20632\tTrain Epoch: 1 [14080/22587 (62.32%)]\tLoss: 0.213500037789\n",
      "20632\tTrain Epoch: 1 [14400/22587 (63.74%)]\tLoss: 0.081165067852\n",
      "20632\tTrain Epoch: 1 [14720/22587 (65.16%)]\tLoss: 0.113577879965\n",
      "20632\tTrain Epoch: 1 [15040/22587 (66.57%)]\tLoss: 0.112500794232\n",
      "20632\tTrain Epoch: 1 [15360/22587 (67.99%)]\tLoss: 0.167289078236\n",
      "20632\tTrain Epoch: 1 [15680/22587 (69.41%)]\tLoss: 0.060451492667\n",
      "20632\tTrain Epoch: 1 [16000/22587 (70.82%)]\tLoss: 0.076751753688\n",
      "20632\tTrain Epoch: 1 [16320/22587 (72.24%)]\tLoss: 0.094842754304\n",
      "20632\tTrain Epoch: 1 [16640/22587 (73.65%)]\tLoss: 0.130306541920\n",
      "20632\tTrain Epoch: 1 [16960/22587 (75.07%)]\tLoss: 0.092875324190\n",
      "20632\tTrain Epoch: 1 [17280/22587 (76.49%)]\tLoss: 0.065762206912\n",
      "20632\tTrain Epoch: 1 [17600/22587 (77.90%)]\tLoss: 0.084350034595\n",
      "20632\tTrain Epoch: 1 [17920/22587 (79.32%)]\tLoss: 0.066793777049\n",
      "20632\tTrain Epoch: 1 [18240/22587 (80.74%)]\tLoss: 0.161687418818\n",
      "20632\tTrain Epoch: 1 [18560/22587 (82.15%)]\tLoss: 0.139767020941\n",
      "20632\tTrain Epoch: 1 [18880/22587 (83.57%)]\tLoss: 0.088864408433\n",
      "20632\tTrain Epoch: 1 [19200/22587 (84.99%)]\tLoss: 0.131687015295\n",
      "20632\tTrain Epoch: 1 [19520/22587 (86.40%)]\tLoss: 0.080619990826\n",
      "20632\tTrain Epoch: 1 [19840/22587 (87.82%)]\tLoss: 0.066843941808\n",
      "20632\tTrain Epoch: 1 [20160/22587 (89.24%)]\tLoss: 0.045023471117\n",
      "20632\tTrain Epoch: 1 [20480/22587 (90.65%)]\tLoss: 0.137153401971\n",
      "20632\tTrain Epoch: 1 [20800/22587 (92.07%)]\tLoss: 0.082931838930\n",
      "20632\tTrain Epoch: 1 [21120/22587 (93.48%)]\tLoss: 0.142401084304\n",
      "20632\tTrain Epoch: 1 [21440/22587 (94.90%)]\tLoss: 0.133557438850\n",
      "20632\tTrain Epoch: 1 [21760/22587 (96.32%)]\tLoss: 0.146910369396\n",
      "20632\tTrain Epoch: 1 [22080/22587 (97.73%)]\tLoss: 0.092282839119\n",
      "20632\tTrain Epoch: 1 [22400/22587 (99.15%)]\tLoss: 0.103856109083\n",
      "20632\tTrain Epoch: 2 [0/22587 (0.00%)]\tLoss: 0.068163849413\n",
      "20632\tTrain Epoch: 2 [320/22587 (1.42%)]\tLoss: 0.106175392866\n",
      "20632\tTrain Epoch: 2 [640/22587 (2.83%)]\tLoss: 0.061032366008\n",
      "20632\tTrain Epoch: 2 [960/22587 (4.25%)]\tLoss: 0.060265693814\n",
      "20632\tTrain Epoch: 2 [1280/22587 (5.67%)]\tLoss: 0.126248732209\n",
      "20632\tTrain Epoch: 2 [1600/22587 (7.08%)]\tLoss: 0.101248517632\n",
      "20632\tTrain Epoch: 2 [1920/22587 (8.50%)]\tLoss: 0.079601727426\n",
      "20632\tTrain Epoch: 2 [2240/22587 (9.92%)]\tLoss: 0.117203913629\n",
      "20632\tTrain Epoch: 2 [2560/22587 (11.33%)]\tLoss: 0.142042860389\n",
      "20632\tTrain Epoch: 2 [2880/22587 (12.75%)]\tLoss: 0.108422905207\n",
      "20632\tTrain Epoch: 2 [3200/22587 (14.16%)]\tLoss: 0.067933164537\n",
      "20632\tTrain Epoch: 2 [3520/22587 (15.58%)]\tLoss: 0.097780570388\n",
      "20632\tTrain Epoch: 2 [3840/22587 (17.00%)]\tLoss: 0.095068305731\n",
      "20632\tTrain Epoch: 2 [4160/22587 (18.41%)]\tLoss: 0.146565154195\n",
      "20632\tTrain Epoch: 2 [4480/22587 (19.83%)]\tLoss: 0.028656216338\n",
      "20632\tTrain Epoch: 2 [4800/22587 (21.25%)]\tLoss: 0.215064033866\n",
      "20632\tTrain Epoch: 2 [5120/22587 (22.66%)]\tLoss: 0.085195638239\n",
      "20632\tTrain Epoch: 2 [5440/22587 (24.08%)]\tLoss: 0.066599711776\n",
      "20632\tTrain Epoch: 2 [5760/22587 (25.50%)]\tLoss: 0.027096886188\n",
      "20632\tTrain Epoch: 2 [6080/22587 (26.91%)]\tLoss: 0.053722579032\n",
      "20632\tTrain Epoch: 2 [6400/22587 (28.33%)]\tLoss: 0.049579478800\n",
      "20632\tTrain Epoch: 2 [6720/22587 (29.75%)]\tLoss: 0.056573837996\n",
      "20632\tTrain Epoch: 2 [7040/22587 (31.16%)]\tLoss: 0.053039811552\n",
      "20632\tTrain Epoch: 2 [7360/22587 (32.58%)]\tLoss: 0.098651543260\n",
      "20632\tTrain Epoch: 2 [7680/22587 (33.99%)]\tLoss: 0.055278487504\n",
      "20632\tTrain Epoch: 2 [8000/22587 (35.41%)]\tLoss: 0.129558950663\n",
      "20632\tTrain Epoch: 2 [8320/22587 (36.83%)]\tLoss: 0.025476191193\n",
      "20632\tTrain Epoch: 2 [8640/22587 (38.24%)]\tLoss: 0.098785459995\n",
      "20632\tTrain Epoch: 2 [8960/22587 (39.66%)]\tLoss: 0.099657177925\n",
      "20632\tTrain Epoch: 2 [9280/22587 (41.08%)]\tLoss: 0.059159379452\n",
      "20632\tTrain Epoch: 2 [9600/22587 (42.49%)]\tLoss: 0.074592247605\n",
      "20632\tTrain Epoch: 2 [9920/22587 (43.91%)]\tLoss: 0.143750891089\n",
      "20632\tTrain Epoch: 2 [10240/22587 (45.33%)]\tLoss: 0.027172971517\n",
      "20632\tTrain Epoch: 2 [10560/22587 (46.74%)]\tLoss: 0.066142186522\n",
      "20632\tTrain Epoch: 2 [10880/22587 (48.16%)]\tLoss: 0.013378102332\n",
      "20632\tTrain Epoch: 2 [11200/22587 (49.58%)]\tLoss: 0.036778192967\n",
      "20632\tTrain Epoch: 2 [11520/22587 (50.99%)]\tLoss: 0.041339576244\n",
      "20632\tTrain Epoch: 2 [11840/22587 (52.41%)]\tLoss: 0.040793959051\n",
      "20632\tTrain Epoch: 2 [12160/22587 (53.82%)]\tLoss: 0.098703965545\n",
      "20632\tTrain Epoch: 2 [12480/22587 (55.24%)]\tLoss: 0.081863716245\n",
      "20632\tTrain Epoch: 2 [12800/22587 (56.66%)]\tLoss: 0.026642233133\n",
      "20632\tTrain Epoch: 2 [13120/22587 (58.07%)]\tLoss: 0.035755496472\n",
      "20632\tTrain Epoch: 2 [13440/22587 (59.49%)]\tLoss: 0.062259756029\n",
      "20632\tTrain Epoch: 2 [13760/22587 (60.91%)]\tLoss: 0.042363416404\n",
      "20632\tTrain Epoch: 2 [14080/22587 (62.32%)]\tLoss: 0.015368400142\n",
      "20632\tTrain Epoch: 2 [14400/22587 (63.74%)]\tLoss: 0.102266833186\n",
      "20632\tTrain Epoch: 2 [14720/22587 (65.16%)]\tLoss: 0.297466039658\n",
      "20632\tTrain Epoch: 2 [15040/22587 (66.57%)]\tLoss: 0.056862421334\n",
      "20632\tTrain Epoch: 2 [15360/22587 (67.99%)]\tLoss: 0.084874242544\n",
      "20632\tTrain Epoch: 2 [15680/22587 (69.41%)]\tLoss: 0.033037681133\n",
      "20632\tTrain Epoch: 2 [16000/22587 (70.82%)]\tLoss: 0.077056512237\n",
      "20632\tTrain Epoch: 2 [16320/22587 (72.24%)]\tLoss: 0.014903288335\n",
      "20632\tTrain Epoch: 2 [16640/22587 (73.65%)]\tLoss: 0.070766523480\n",
      "20632\tTrain Epoch: 2 [16960/22587 (75.07%)]\tLoss: 0.112207852304\n",
      "20632\tTrain Epoch: 2 [17280/22587 (76.49%)]\tLoss: 0.062801137567\n",
      "20632\tTrain Epoch: 2 [17600/22587 (77.90%)]\tLoss: 0.024542432278\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "20632\tTrain Epoch: 2 [17920/22587 (79.32%)]\tLoss: 0.085207156837\n",
      "20632\tTrain Epoch: 2 [18240/22587 (80.74%)]\tLoss: 0.062715381384\n",
      "20632\tTrain Epoch: 2 [18560/22587 (82.15%)]\tLoss: 0.196202084422\n",
      "20632\tTrain Epoch: 2 [18880/22587 (83.57%)]\tLoss: 0.134793311357\n",
      "20632\tTrain Epoch: 2 [19200/22587 (84.99%)]\tLoss: 0.044903233647\n",
      "20632\tTrain Epoch: 2 [19520/22587 (86.40%)]\tLoss: 0.037119306624\n",
      "20632\tTrain Epoch: 2 [19840/22587 (87.82%)]\tLoss: 0.044805184007\n",
      "20632\tTrain Epoch: 2 [20160/22587 (89.24%)]\tLoss: 0.067375332117\n",
      "20632\tTrain Epoch: 2 [20480/22587 (90.65%)]\tLoss: 0.028314827010\n",
      "20632\tTrain Epoch: 2 [20800/22587 (92.07%)]\tLoss: 0.097856707871\n",
      "20632\tTrain Epoch: 2 [21120/22587 (93.48%)]\tLoss: 0.028983391821\n",
      "20632\tTrain Epoch: 2 [21440/22587 (94.90%)]\tLoss: 0.036553006619\n",
      "20632\tTrain Epoch: 2 [21760/22587 (96.32%)]\tLoss: 0.032814148813\n",
      "20632\tTrain Epoch: 2 [22080/22587 (97.73%)]\tLoss: 0.017245352268\n",
      "20632\tTrain Epoch: 2 [22400/22587 (99.15%)]\tLoss: 0.116387799382\n",
      "20632\tTrain Epoch: 3 [0/22587 (0.00%)]\tLoss: 0.083038598299\n",
      "20632\tTrain Epoch: 3 [320/22587 (1.42%)]\tLoss: 0.051355447620\n",
      "20632\tTrain Epoch: 3 [640/22587 (2.83%)]\tLoss: 0.037479009479\n",
      "20632\tTrain Epoch: 3 [960/22587 (4.25%)]\tLoss: 0.163382321596\n",
      "20632\tTrain Epoch: 3 [1280/22587 (5.67%)]\tLoss: 0.151731729507\n",
      "20632\tTrain Epoch: 3 [1600/22587 (7.08%)]\tLoss: 0.052046611905\n",
      "20632\tTrain Epoch: 3 [1920/22587 (8.50%)]\tLoss: 0.040490005165\n",
      "20632\tTrain Epoch: 3 [2240/22587 (9.92%)]\tLoss: 0.119232334197\n",
      "20632\tTrain Epoch: 3 [2560/22587 (11.33%)]\tLoss: 0.051213789731\n",
      "20632\tTrain Epoch: 3 [2880/22587 (12.75%)]\tLoss: 0.038229707628\n",
      "20632\tTrain Epoch: 3 [3200/22587 (14.16%)]\tLoss: 0.080159932375\n",
      "20632\tTrain Epoch: 3 [3520/22587 (15.58%)]\tLoss: 0.062770858407\n",
      "20632\tTrain Epoch: 3 [3840/22587 (17.00%)]\tLoss: 0.068788476288\n",
      "20632\tTrain Epoch: 3 [4160/22587 (18.41%)]\tLoss: 0.107502549887\n",
      "20632\tTrain Epoch: 3 [4480/22587 (19.83%)]\tLoss: 0.033699437976\n",
      "20632\tTrain Epoch: 3 [4800/22587 (21.25%)]\tLoss: 0.066851876676\n",
      "20632\tTrain Epoch: 3 [5120/22587 (22.66%)]\tLoss: 0.087649516761\n",
      "20632\tTrain Epoch: 3 [5440/22587 (24.08%)]\tLoss: 0.057514298707\n",
      "20632\tTrain Epoch: 3 [5760/22587 (25.50%)]\tLoss: 0.123113490641\n",
      "20632\tTrain Epoch: 3 [6080/22587 (26.91%)]\tLoss: 0.174426272511\n",
      "20632\tTrain Epoch: 3 [6400/22587 (28.33%)]\tLoss: 0.011918358505\n",
      "20632\tTrain Epoch: 3 [6720/22587 (29.75%)]\tLoss: 0.047110997140\n",
      "20632\tTrain Epoch: 3 [7040/22587 (31.16%)]\tLoss: 0.101677097380\n",
      "20632\tTrain Epoch: 3 [7360/22587 (32.58%)]\tLoss: 0.126820027828\n",
      "20632\tTrain Epoch: 3 [7680/22587 (33.99%)]\tLoss: 0.077451720834\n",
      "20632\tTrain Epoch: 3 [8000/22587 (35.41%)]\tLoss: 0.061186194420\n",
      "20632\tTrain Epoch: 3 [8320/22587 (36.83%)]\tLoss: 0.036615017802\n",
      "20632\tTrain Epoch: 3 [8640/22587 (38.24%)]\tLoss: 0.035401567817\n",
      "20632\tTrain Epoch: 3 [8960/22587 (39.66%)]\tLoss: 0.029194045812\n",
      "20632\tTrain Epoch: 3 [9280/22587 (41.08%)]\tLoss: 0.064756043255\n",
      "20632\tTrain Epoch: 3 [9600/22587 (42.49%)]\tLoss: 0.073789156973\n",
      "20632\tTrain Epoch: 3 [9920/22587 (43.91%)]\tLoss: 0.071544952691\n",
      "20632\tTrain Epoch: 3 [10240/22587 (45.33%)]\tLoss: 0.022304452956\n",
      "20632\tTrain Epoch: 3 [10560/22587 (46.74%)]\tLoss: 0.117808662355\n",
      "20632\tTrain Epoch: 3 [10880/22587 (48.16%)]\tLoss: 0.046829782426\n",
      "20632\tTrain Epoch: 3 [11200/22587 (49.58%)]\tLoss: 0.119917295873\n",
      "20632\tTrain Epoch: 3 [11520/22587 (50.99%)]\tLoss: 0.134579718113\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-4-c896ae3f5020>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     41\u001b[0m     \u001b[1;31m#使用固定缓冲区\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     42\u001b[0m     \u001b[0mdataloader_kwargs\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m{\u001b[0m\u001b[1;34m'pin_memory'\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;32mTrue\u001b[0m\u001b[1;33m}\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0muse_cuda\u001b[0m \u001b[1;32melse\u001b[0m \u001b[1;33m{\u001b[0m\u001b[1;33m}\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 43\u001b[1;33m     \u001b[0mvgg_train\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mvgg16\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mdevice\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdataloader_kwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;32m<ipython-input-3-d0780b60f95b>\u001b[0m in \u001b[0;36mvgg_train\u001b[1;34m(args, vgg, device, dataloader_kwargs)\u001b[0m\n\u001b[0;32m     10\u001b[0m     \u001b[1;31m#开始训练，训练epoches次\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     11\u001b[0m     \u001b[1;32mfor\u001b[0m \u001b[0mepoch\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0margs\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"epochs\"\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 12\u001b[1;33m         \u001b[0mglobal_step\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mvgg_train_epoch\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mepoch\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvgg\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdevice\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrain_loader\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0moptimizer\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mglobal_step\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     13\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     14\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m<ipython-input-3-d0780b60f95b>\u001b[0m in \u001b[0;36mvgg_train_epoch\u001b[1;34m(epoch, args, vgg, device, data_loader, optimizer, global_step)\u001b[0m\n\u001b[0;32m     24\u001b[0m         \u001b[0moutput\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mF\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlog_softmax\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mvgg\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mto\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdevice\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     25\u001b[0m         \u001b[1;31m#预测值与标准值计算损失\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 26\u001b[1;33m         \u001b[0mloss\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mF\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnll_loss\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0moutput\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnarrow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mtarget\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mto\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdevice\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     27\u001b[0m         \u001b[1;31m#计算梯度\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     28\u001b[0m         \u001b[0mloss\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbackward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "#数据加载\n",
    "from torchvision.datasets import ImageFolder\n",
    "from torchvision import datasets,transforms,utils,models\n",
    "import visdom\n",
    "import numpy as np\n",
    "viz = visdom.Visdom(port=8097, server=\"127.0.0.1\",env=\"Test\")\n",
    "# line updates\n",
    "loss_win = viz.line(np.arange(1))\n",
    "simple_transform = transforms.Compose([transforms.Resize((224,224))\n",
    "                                       ,transforms.ToTensor()\n",
    "                                       ,transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n",
    "                                      ])\n",
    "train_data = ImageFolder('../chapter4/DogVsCatData/train',simple_transform)\n",
    "#用微调好的网络传入数据重新训练模型\n",
    "#超参数及默认值\n",
    "args={\n",
    "    'batch_size':32,\n",
    "    'epochs':10,\n",
    "    'lr':0.0001,\n",
    "    'momentum':0.5,\n",
    "    'seed':1,\n",
    "    'log_interval':30,\n",
    "    'train_data':train_data,\n",
    "    'loss_win':loss_win\n",
    "}\n",
    "use_cuda=True if torch.cuda.is_available() else False\n",
    "\n",
    "if __name__==\"__main__\":\n",
    "    #运行时设备\n",
    "    device = torch.device(\"cuda:0\" if use_cuda else \"cpu\")\n",
    "    vgg16 = models.vgg16(pretrained=True)\n",
    "    \n",
    "    #冻结网络层\n",
    "    for param in vgg16.features.parameters(): \n",
    "        param.requires_grad = False                                                              \n",
    "    #微调网络\n",
    "    fc_features = vgg16.classifier[6].in_features  \n",
    "    #修改类别为2\n",
    "    vgg16.classifier[6] = nn.Linear(fc_features,2) \n",
    "    vgg16.cuda()\n",
    "    #使用固定缓冲区\n",
    "    dataloader_kwargs = {'pin_memory': True} if use_cuda else {}\n",
    "    vgg_train(args,vgg16,device, dataloader_kwargs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
